home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / net_amigaudp.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  11KB  |  449 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // net_udp.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. #include <exec/exec.h>
  25. #include <powerup/ppcproto/exec.h>
  26.  
  27. #include <sys/types.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <netdb.h>
  31. #include <sys/param.h>
  32. #include <sys/ioctl.h>
  33. #include <errno.h>
  34.  
  35. #include <powerup/ppcproto/socket.h>
  36.  
  37. extern void I_Error (char *error, ...);
  38. extern cvar_t hostname;
  39.  
  40. struct Library *SocketBase = NULL;
  41.  
  42. static int net_acceptsocket = -1;        // socket for fielding new connections
  43. static int net_controlsocket = -1;
  44. static int net_broadcastsocket = 0;
  45. static struct qsockaddr broadcastaddr;
  46.  
  47. static unsigned long myAddr;
  48.  
  49. #include "net_udp.h"
  50.  
  51. //=============================================================================
  52.  
  53. int UDP_Init (void)
  54. {
  55.     struct hostent *local;
  56.     char    buff[MAXHOSTNAMELEN];
  57.     struct qsockaddr addr;
  58.     char *colon;
  59.     
  60. //    Con_Printf ("UDP_Init()\n");
  61.     if (COM_CheckParm ("-noudp"))
  62.         return -1;
  63.  
  64.         if ((SocketBase = OpenLibrary ("bsdsocket.library", 0)) == NULL) {
  65.           Con_Printf ("OpenLibrary(\"bsdsocket.library\") failed, no networking available\n");
  66.           return -1;
  67.         }
  68.  
  69.     // determine my name & address
  70.     gethostname(buff, MAXHOSTNAMELEN);
  71.     local = gethostbyname(buff);
  72.     myAddr = *(int *)local->h_addr_list[0];
  73.  
  74.     // if the quake hostname isn't set, set it to the machine name
  75.     if (Q_strcmp(hostname.string, "UNNAMED") == 0)
  76.     {
  77.         buff[15] = 0;
  78.         Cvar_Set ("hostname", buff);
  79.     }
  80.  
  81.     if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
  82.         Sys_Error("UDP_Init: Unable to open control socket\n");
  83.  
  84.     ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
  85.     ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
  86.     ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
  87.  
  88.     UDP_GetSocketAddr (net_controlsocket, &addr);
  89.     Q_strcpy(my_tcpip_address,  UDP_AddrToString (&addr));
  90.     colon = Q_strrchr (my_tcpip_address, ':');
  91.     if (colon)
  92.         *colon = 0;
  93.  
  94.     Con_Printf("UDP Initialized\n");
  95.     tcpipAvailable = true;
  96.  
  97.     return net_controlsocket;
  98. }
  99.  
  100. //=============================================================================
  101.  
  102. void UDP_Shutdown (void)
  103. {
  104. //    Con_Printf ("UDP_Shutdown()\n");
  105.     if (SocketBase != NULL) {
  106.         UDP_Listen (false);
  107.         if (net_controlsocket != -1) {
  108.             UDP_CloseSocket (net_controlsocket);
  109.             net_controlsocket = -1;
  110.         }
  111.         CloseLibrary (SocketBase);
  112.         SocketBase = NULL;
  113.     }
  114. }
  115.  
  116. //=============================================================================
  117.  
  118. void UDP_Listen (qboolean state)
  119. {
  120. //    Con_Printf ("UDP_Listen()\n");
  121.     // enable listening
  122.     if (state)
  123.     {
  124.         if (net_acceptsocket != -1)
  125.             return;
  126.         if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
  127.             Sys_Error ("UDP_Listen: Unable to open accept socket\n");
  128.         return;
  129.     }
  130.  
  131.     // disable listening
  132.     if (net_acceptsocket == -1)
  133.         return;
  134.     UDP_CloseSocket (net_acceptsocket);
  135.     net_acceptsocket = -1;
  136. }
  137.  
  138. //=============================================================================
  139.  
  140. int UDP_OpenSocket (int port)
  141. {
  142.     int newsocket;
  143.     struct sockaddr_in address;
  144.     long _true = true;
  145.  
  146. //    Con_Printf ("UDP_OpenSocket()\n");
  147.     if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  148.         return -1;
  149.  
  150.     if (IoctlSocket (newsocket, FIONBIO, (char *)&_true) == -1)
  151.         goto ErrorReturn;
  152.  
  153.     address.sin_family = AF_INET;
  154.     address.sin_addr.s_addr = INADDR_ANY;
  155.     address.sin_port = htons(port);
  156.     if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  157.         goto ErrorReturn;
  158.  
  159.     return newsocket;
  160.  
  161. ErrorReturn:
  162.     CloseSocket (newsocket);
  163.     return -1;
  164. }
  165.  
  166. //=============================================================================
  167.  
  168. int UDP_CloseSocket (int socket)
  169. {
  170. //    Con_Printf ("UDP_CloseSocket()\n");
  171.     if (socket == net_broadcastsocket)
  172.         net_broadcastsocket = 0;
  173.     return CloseSocket (socket);
  174. }
  175.  
  176.  
  177. //=============================================================================
  178. /*
  179. ============
  180. PartialIPAddress
  181.  
  182. this lets you type only as much of the net address as required, using
  183. the local network components to fill in the rest
  184. ============
  185. */
  186. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  187. {
  188.     char buff[256];
  189.     char *b;
  190.     int addr;
  191.     int num;
  192.     int mask;
  193.     int run;
  194.     int port;
  195.     
  196. //    Con_Printf ("UDP_PartialIPAddress()\n");
  197.     buff[0] = '.';
  198.     b = buff;
  199.     strcpy(buff+1, in);
  200.     if (buff[1] == '.')
  201.         b++;
  202.  
  203.     addr = 0;
  204.     mask=-1;
  205.     while (*b == '.')
  206.     {
  207.         b++;
  208.         num = 0;
  209.         run = 0;
  210.         while (!( *b < '0' || *b > '9'))
  211.         {
  212.           num = num*10 + *b++ - '0';
  213.           if (++run > 3)
  214.               return -1;
  215.         }
  216.         if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  217.             return -1;
  218.         if (num < 0 || num > 255)
  219.             return -1;
  220.         mask<<=8;
  221.         addr = (addr<<8) + num;
  222.     }
  223.     
  224.     if (*b++ == ':')
  225.         port = Q_atoi(b);
  226.     else
  227.         port = net_hostport;
  228.  
  229.     ((struct sockaddr_in *)hostaddr)->sin_family = AF_INET;
  230.     ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);    
  231.     ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  232.     
  233.     return 0;
  234. }
  235. //=============================================================================
  236.  
  237. int UDP_Connect (int socket, struct qsockaddr *addr)
  238. {
  239. //    Con_Printf ("UDP_Connect()\n");
  240.     return 0;
  241. }
  242.  
  243. //=============================================================================
  244.  
  245. int UDP_CheckNewConnections (void)
  246. {
  247.     long    available;
  248.  
  249. //    Con_Printf ("UDP_CheckNewConnections()\n");
  250.     if (net_acceptsocket == -1)
  251.         return -1;
  252.  
  253.     if (IoctlSocket (net_acceptsocket, FIONREAD, (char *)&available) == -1)
  254.         Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
  255.     if (available)
  256.         return net_acceptsocket;
  257.     return -1;
  258. }
  259.  
  260. //=============================================================================
  261.  
  262. int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  263. {
  264.     LONG addrlen = sizeof (struct qsockaddr);
  265.     int ret;
  266.     long err;
  267.  
  268. //    Con_Printf ("UDP_Read()\n");
  269.     ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  270.     err = Errno();
  271.     if (ret == -1 && (err == EWOULDBLOCK || err == ECONNREFUSED))
  272.         return 0;
  273.     return ret;
  274. }
  275.  
  276. //=============================================================================
  277.  
  278. int UDP_MakeSocketBroadcastCapable (int socket)
  279. {
  280.     int                i = 1;
  281.  
  282. //    Con_Printf ("UDP_MakeSocketBroadcastCapable()\n");
  283.     // make this socket broadcast capable
  284.     if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
  285.         return -1;
  286.     net_broadcastsocket = socket;
  287.  
  288.     return 0;
  289. }
  290.  
  291. //=============================================================================
  292.  
  293. int UDP_Broadcast (int socket, byte *buf, int len)
  294. {
  295.     int ret;
  296.  
  297. //    Con_Printf ("UDP_Broadcast()\n");
  298.     if (socket != net_broadcastsocket)
  299.     {
  300.         if (net_broadcastsocket != 0)
  301.             Sys_Error("Attempted to use multiple broadcasts sockets\n");
  302.         ret = UDP_MakeSocketBroadcastCapable (socket);
  303.         if (ret == -1)
  304.         {
  305.             Con_Printf("Unable to make socket broadcast capable\n");
  306.             return ret;
  307.         }
  308.     }
  309.  
  310.     return UDP_Write (socket, buf, len, &broadcastaddr);
  311. }
  312.  
  313. //=============================================================================
  314.  
  315. int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  316. {
  317.     int ret;
  318.  
  319. //    Con_Printf ("UDP_Write()\n");
  320.     ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  321.     if (ret == -1 && Errno() == EWOULDBLOCK)
  322.         return 0;
  323.     return ret;
  324. }
  325.  
  326. //=============================================================================
  327.  
  328. char *UDP_AddrToString (struct qsockaddr *addr)
  329. {
  330.     static char buffer[22];
  331.     int haddr;
  332.  
  333. //    Con_Printf ("UDP_AddrToString()\n");
  334.     haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  335.     sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff,
  336.             (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff,
  337.             ntohs(((struct sockaddr_in *)addr)->sin_port));
  338.     return buffer;
  339. }
  340.  
  341. //=============================================================================
  342.  
  343. int UDP_StringToAddr (char *string, struct qsockaddr *addr)
  344. {
  345.     int ha1, ha2, ha3, ha4, hp;
  346.     int ipaddr;
  347.  
  348. //    Con_Printf ("UDP_StringToAddr()\n");
  349.     sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  350.     ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  351.  
  352.     ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  353.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  354.     ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  355.     return 0;
  356. }
  357.  
  358. //=============================================================================
  359.  
  360. int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
  361. {
  362.     LONG addrlen = sizeof(struct qsockaddr);
  363.     unsigned int a;
  364.  
  365. //    Con_Printf ("UDP_GetSocketAddr()\n");
  366.     Q_memset(addr, 0, sizeof(struct qsockaddr));
  367.     getsockname(socket, (struct sockaddr *)addr, &addrlen);
  368.     a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  369.     if (a == 0 || a == inet_addr("127.0.0.1"))
  370.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  371.  
  372.     return 0;
  373. }
  374.  
  375. //=============================================================================
  376.  
  377. int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
  378. {
  379.     struct hostent *hostentry;
  380.  
  381. //    Con_Printf ("UDP_GetNameFromAddr()\n");
  382.     hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  383.     if (hostentry)
  384.     {
  385.         Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  386.         return 0;
  387.     }
  388.  
  389.     Q_strcpy (name, UDP_AddrToString (addr));
  390.     return 0;
  391. }
  392.  
  393. //=============================================================================
  394.  
  395. int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
  396. {
  397.     struct hostent *hostentry;
  398.  
  399. //    Con_Printf ("UDP_GetAddrFromName()\n");
  400.     if (name[0] >= '0' && name[0] <= '9')
  401.         return PartialIPAddress (name, addr);
  402.     
  403.     hostentry = gethostbyname (name);
  404.     if (!hostentry)
  405.         return -1;
  406.  
  407.     ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  408.     ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);    
  409.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  410.  
  411.     return 0;
  412. }
  413.  
  414. //=============================================================================
  415.  
  416. int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  417. {
  418. //    Con_Printf ("UDP_AddrCompare()\n");
  419.  
  420.     if (((struct sockaddr_in *)addr1)->sin_family !=
  421.             ((struct sockaddr_in *)addr2)->sin_family)
  422.         return -1;
  423.  
  424.     if (((struct sockaddr_in *)addr1)->sin_addr.s_addr !=
  425.             ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  426.         return -1;
  427.  
  428.     if (((struct sockaddr_in *)addr1)->sin_port !=
  429.             ((struct sockaddr_in *)addr2)->sin_port)
  430.         return 1;
  431.  
  432.     return 0;
  433. }
  434.  
  435. //=============================================================================
  436.  
  437. int UDP_GetSocketPort (struct qsockaddr *addr)
  438. {
  439. //    Con_Printf ("UDP_GetSocketPort()\n");
  440.     return ntohs(((struct sockaddr_in *)addr)->sin_port);
  441. }
  442.  
  443.  
  444. int UDP_SetSocketPort (struct qsockaddr *addr, int port)
  445. {
  446.     ((struct sockaddr_in *)addr)->sin_port = htons(port);
  447.     return 0;
  448. }
  449.